package leetcode.code149;

import java.util.HashMap;
import java.util.Map;

public class Solution extends Solution149 {

	@Override
	public int maxPoints(int[][] points) {
		int len = points.length;
		Map<Integer, Map<Integer, Map<Integer, Integer>>> map1 = new HashMap<>();
		Map<Integer, Integer> mapx = new HashMap<>();
		Map<Integer, Integer> mapy = new HashMap<>();
		Map<Integer, Integer> map0 = new HashMap<>();
		for (int i = 0; i < len - 1; i++) {
			for (int j = i + 1; j < len; j++) {
				int[] p1 = points[i];
				int[] p2 = points[j];
				int x = p1[0] - p2[0];
				int y = p1[1] - p2[1];
				if (x != 0 && y != 0) {
					int gcd = this.gcd(x, y);
					int xx = x / gcd;
					int yx = y / gcd;
					this.update(map1, i, xx, yx);
					this.update(map1, j, xx, yx);
				} else if (x == 0 && y != 0) {
					int numx = mapx.getOrDefault(i, 0) + 1;
					mapx.put(i, numx);
					int numy = mapx.getOrDefault(j, 0) + 1;
					mapx.put(j, numy);
				} else if (x != 0 && y == 0) {
					int numx = mapy.getOrDefault(i, 0) + 1;
					mapy.put(i, numx);
					int numy = mapy.getOrDefault(j, 0) + 1;
					mapy.put(j, numy);
				} else {
					int numx = map0.getOrDefault(i, 0) + 1;
					map0.put(i, numx);
					int numy = map0.getOrDefault(j, 0) + 1;
					map0.put(i, numy);
				}
			}
		}
		int max = 0;
		for (int i = 0; i < len - 1; i++) {
			int numx = mapx.getOrDefault(i, 0);
			int numy = mapy.getOrDefault(i, 0);
			Map<Integer, Map<Integer, Integer>> m = map1.get(i);
			int numxy = 1;
			if (m != null) {
				for (int key1 : m.keySet()) {
					Map<Integer, Integer> m1 = m.get(key1);
					for (int key2 : m1.keySet()) {
						numxy = Math.max(m1.get(key2), numxy);
					}
				}
			}
			int num = Math.max(numx, Math.max(numy, numxy));
			int num0 = map0.getOrDefault(i, 0);
			max = Math.max(max, num + num0);
		}
		return max + 1;
	}

	private void update(Map<Integer, Map<Integer, Map<Integer, Integer>>> map1, int index, int x, int y) {
		Map<Integer, Map<Integer, Integer>> map2 = map1.getOrDefault(index, new HashMap<>());
		Map<Integer, Integer> map3 = map2.getOrDefault(x, new HashMap<>());
		int num1 = map3.getOrDefault(y, 0) + 1;
		map3.put(y, num1);
		map2.put(x, map3);
		map1.put(index, map2);
	}

	public int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	public static void main(String[] args) {
		Solution so = new Solution();
		so.debug1();
		so.debug2();
		so.debug3();
		so.debug5();

//		int i = so.gcd(12, 15);
//		System.out.println(i);
	}

}
